﻿using System;
using System.Collections.Generic;
using System.Linq;
using zkemkeeper;

using ZKLibrarys.Constant;
using ZKLibrarys.Models;

namespace ZKLibrarys.zkem
{
    /// <summary>
    /// 中控考勤机相关API
    /// (基本都是TFT机器的API,BW设备的一般没写)
    /// </summary>
    public class ZKAPI
    {
        #region 1.考勤机配置
        /// <summary>
        /// 从配置文件读取所有中控考勤机配置到ZKGConf中的实体对象集合
        /// (模式为先清空,再添加)
        /// </summary>
        public static void InitZKMachinesList()
        {
            //初始化
            ZKConfig.InitZKConfig();
            //从配置文件读取
            ZKGConf.ZKMachines.Clear();
            foreach (string[] item in ZKConfig.GetDevices())
            {
                ZKGConf.ZKMachines.Add(new ModelZKMachine()
                {
                    ID = Convert.ToInt32(item[0]),
                    Name = Convert.ToString(item[1]),
                    IP = Convert.ToString(item[2]),
                    Port = Convert.ToInt32(item[3]),
                    Pass = Convert.ToInt32(item[4]),
                    ZKMachineClass = new zkemkeeper.CZKEMClass(),
                    IsConnected = false
                });
            }
        }

        /// <summary>
        /// 将GConf中的考勤机配置实体对象保存到配置文件
        /// (模式为先清空,再添加保存)
        /// </summary>
        public static void SaveToConf()
        {
            ZKConfig.DelDevices();
            foreach (ModelZKMachine item in ZKGConf.ZKMachines)
            {
                ZKConfig.AddDevice(item.ID.ToString(), item.Name, item.IP, item.Port, item.Pass);
            }
        }
        #endregion

        #region 2.连接与断开考勤机
        /// <summary>
        /// 连接指定机号的考勤机
        /// </summary>
        /// <param name="ID">机器号</param>
        /// <returns></returns>
        public static bool ConnZKMachine(string ID)
        {
            int errCode = 0;
            ModelZKMachine zkm = ZKGConf.ZKMachines.First(t => t.ID == Convert.ToInt32(ID));
            if (zkm.ZKMachineClass == null)
            {
                zkm.ZKMachineClass = new CZKEMClass();
            }
            zkm.ZKMachineClass.GetConnectStatus(ref errCode);
            if (errCode == ErrorCode.ConnectSuccess)
            {
                zkm.ZKMachineClass.Disconnect();
            }
            zkm.ZKMachineClass.SetCommPassword(zkm.Pass);
            zkm.ZKMachineClass.MachineNumber = zkm.ID;
            if (zkm.ZKMachineClass.Connect_Net(zkm.IP, zkm.Port))
            {
                zkm.IsConnected = true;
                return true;
            }
            else
            {
                zkm.IsConnected = false;
                return false;
            }

        }

        /// <summary>
        /// 连接所有的考勤设备
        /// </summary>
        public static void ConnAllZKMachine()
        {
            int errCode = 0;
            foreach (ModelZKMachine item in ZKGConf.ZKMachines)
            {
                //检测是否已经存在
                if (item.ZKMachineClass != null)
                {
                    item.ZKMachineClass.GetConnectStatus(ref errCode);
                    if (errCode == ErrorCode.ConnectSuccess)
                    {
                        item.ZKMachineClass.Disconnect();
                    }
                    item.ZKMachineClass.SetCommPassword(item.Pass);
                    item.ZKMachineClass.MachineNumber = item.ID;
                    if (item.ZKMachineClass.Connect_Net(item.IP, item.Port))
                    {
                        item.IsConnected = true;
                    }
                    else
                    {
                        item.IsConnected = false;
                    }
                }
                else
                {
                    item.ZKMachineClass = new CZKEMClass();
                    item.ZKMachineClass.SetCommPassword(item.Pass);
                    item.ZKMachineClass.MachineNumber = item.ID;
                    if (item.ZKMachineClass.Connect_Net(item.IP, item.Port))
                    {
                        item.IsConnected = true;
                    }
                    else
                    {
                        item.IsConnected = false;
                    }
                }

            }
        }

        /// <summary>
        /// 断开指定考勤机
        /// </summary>
        /// <param name="ID"></param>
        public static void DisconnZKMachine(string ID)
        {
            int errCode = 0;
            ModelZKMachine zkm = ZKGConf.ZKMachines.First(t => t.ID == Convert.ToInt32(ID));
            if (zkm.ZKMachineClass != null)
            {
                zkm.ZKMachineClass.GetConnectStatus(ref errCode);
                if (errCode == ErrorCode.ConnectSuccess)
                {
                    zkm.ZKMachineClass.Disconnect();
                    zkm.IsConnected = false;
                }
            }
        }

        /// <summary>
        /// 断开所有的考勤设备
        /// </summary>
        public static void DisconnAllZKMachine()
        {
            int errCode = 0;
            foreach (ModelZKMachine item in ZKGConf.ZKMachines)
            {
                //检测是否已经存在
                if (item.ZKMachineClass != null)
                {
                    item.ZKMachineClass.GetConnectStatus(ref errCode);
                    if (errCode == ErrorCode.ConnectSuccess)
                    {
                        item.ZKMachineClass.Disconnect();
                        item.IsConnected = false;
                    }
                    else
                    {
                        item.IsConnected = false;
                    }
                }
                else
                {
                    item.IsConnected = false;
                }

                //清空其它信息
                item.UserCurrentNum = 0;
                item.UserTotalNum = 0;
                item.FingerCurrentNum = 0;
                item.FingerTotalNum = 0;
                item.RecordsCurrentNum = 0;
                item.RecordsTotalNum = 0;
                item.PasswordsTotalNum = 0;
                item.AdminsTotalNum = 0;
            }
        }

        #endregion

        #region 3.考勤机一些方法
        /// <summary>
        /// 设置启用或禁用所有已经连接的考勤机
        /// </summary>
        /// <param name="Flag">启用或禁用</param>
        public static void EnableAllDevice(bool Flag)
        {
            foreach (ModelZKMachine item in ZKGConf.ZKMachines)
            {
                if (item.IsConnected)
                {
                    ZKAPIOriginal.EnableDevice(item.ID, Flag);
                }
            }
        }

        /// <summary>
        /// 设置启用或禁用考勤机
        /// </summary>
        /// <param name="ID">考勤机ID</param>
        /// <param name="Flag">启用或禁用</param>
        /// <returns></returns>
        public static bool EnableDevice(int ID,bool Flag)
        {
            return ZKAPIOriginal.EnableDevice(ID, Flag);
        }

        /// <summary>
        /// 获取指定考勤机API类发生的错误代码信息
        /// </summary>
        /// <param name="ID">考勤机ID</param>
        /// <returns></returns>
        public static string GetLastErrorMsg()
        {
            //ZKAPIOriginal.ZKEM = item.ZKMachineClass;
            //ZKAPIOriginal.MachiceNumber = item.ID;
            //return ErrorCode.GetErrMsg(GetLastError(ID));
            throw new NotImplementedException("未完成");
        }

        /// <summary>
        /// 获取最后的错误
        /// </summary>
        /// <param name="ID">考勤机ID</param>
        /// <returns></returns>
        public static string GetLastErrorMsg(int ID)
        {
            int errCode = 0;
            ZKGConf.GetZKClass(ID).GetLastError(errCode);
            return ErrorCode.GetErrMsg(errCode);
        }
        #endregion

        #region 4.考勤机连接后获取设置信息相关处理

        /// <summary>
        /// 初始化所有考勤机的信息数据
        /// </summary>
        /// <returns></returns>
        public static bool InitZKMachineInfo()
        {
            int IValue = 0;
            foreach (ModelZKMachine item in ZKGConf.ZKMachines)
            {
                if (item.IsConnected)
                {
                    //当前用户数
                    item.ZKMachineClass.GetDeviceStatus(item.ID, StatusCode.UserCount, ref IValue);
                    item.UserCurrentNum = IValue;
                    //总计用户数
                    item.ZKMachineClass.GetDeviceStatus(item.ID, StatusCode.UserTotal, ref IValue);
                    item.UserTotalNum = IValue;
                    //当前指纹数
                    item.ZKMachineClass.GetDeviceStatus(item.ID, StatusCode.FingerCount, ref IValue);
                    item.FingerCurrentNum = IValue;
                    //总计指纹数
                    item.ZKMachineClass.GetDeviceStatus(item.ID, StatusCode.FingerTotal, ref IValue);
                    item.FingerTotalNum = IValue;
                    //当前考勤记录数
                    item.ZKMachineClass.GetDeviceStatus(item.ID, StatusCode.RecordCount, ref IValue);
                    item.RecordsCurrentNum = IValue;
                    //总计考勤记录数
                    item.ZKMachineClass.GetDeviceStatus(item.ID, StatusCode.RecordTotal, ref IValue);
                    item.RecordsTotalNum = IValue;
                    //总计密码数
                    item.ZKMachineClass.GetDeviceStatus(item.ID, StatusCode.PassCount, ref IValue);
                    item.PasswordsTotalNum = IValue;
                    //总计管理员数
                    item.ZKMachineClass.GetDeviceStatus(item.ID, StatusCode.AdminCount, ref IValue);
                    item.AdminsTotalNum = IValue;
                }
                else
                {
                    //当前用户数
                    item.UserCurrentNum = 0;
                    //总计用户数
                    item.UserTotalNum = 0;
                    //当前指纹数
                    item.FingerCurrentNum = 0;
                    //总计指纹数
                    item.FingerTotalNum = 0;
                    //当前考勤记录数
                    item.RecordsCurrentNum = 0;
                    //总计考勤记录数
                    item.RecordsTotalNum = 0;
                    //总计密码数
                    item.PasswordsTotalNum = 0;
                    //总计管理员数
                    item.AdminsTotalNum = 0;
                }
            }
            return true;
        }

        /// <summary>
        /// 获取指定考勤机的设备信息
        /// </summary>
        /// <param name="ZKM">设备配置对象</param>
        /// <returns></returns>
        public static ModelMOption GetMacOption(ModelZKMachine ZKM)
        {
            int IValue = 0;
            string SValue = "";
            ModelMOption mmo = new ModelMOption();
            //获取设备的IP地址
            ZKM.ZKMachineClass.GetDeviceIP(ZKM.ID, ref SValue);
            mmo.MIP = SValue;
            Console.WriteLine(IValue.ToString());
            return mmo;
        }
        #endregion

        #region 5.考勤记录处理

        /// <summary>
        /// 按给定的时间点（精确到秒），删除这个时间点前的所有老的考勤记录
        /// 只适应于新架构固件
        /// </summary>
        /// <param name="ID">考勤机ID</param>
        /// <param name="dateTime">要删除哪个时间点前的考勤记录</param>
        /// <returns></returns>
        public static bool ClearGLog(int ID, DateTime dateTime)
        {
            return ZKGConf.GetZKClass(ID).DeleteAttlogByTime(ID, dateTime.ToString("yyyy-MM-dd HH:mm:ss"));
        }


        public delegate void SSR_GetGeneralLogDataEventHandle(string EmpID, string Datetime);

        /// <summary>
        /// 读取内存中的所有考勤记录事件
        /// </summary>
        public static event SSR_GetGeneralLogDataEventHandle SSR_GetGeneralLogDataAdd;

        /// <summary>
        /// 读取内存中所有考勤记录
        /// (适应于TFT,IFACE机子)
        /// </summary>
        /// <param name="ID">考勤机ID</param>
        /// <returns></returns>
        public static List<ModelGLog> SSR_GetGeneralLogData(int ID)
        {
            //变量
            int WorkCode = 0;
            List<ModelGLog> glogs = new List<ModelGLog>();
            string IPAdd = ZKAPIOriginal.GetDeviceIP(ID);

            //读取数据
            while (ZKGConf.GetZKClass(ID).SSR_GetGeneralLogData(
                ID, out string KQEmpID, out int VMode, out int IOMode,
                out int Year, out int Month, out int Day, out int Hour, out int Minute, out int Second, ref WorkCode))
            {

                glogs.Add(new ModelGLog()
                {
                    MachineNumber = ID,
                    EnrollNumber = KQEmpID,
                    VerifyMode = VMode,
                    InOutMode = IOMode,
                    dateTime = new DateTime(Year, Month, Day, Hour, Minute, Second),
                    WorkCode = WorkCode,
                    IPAddress = IPAdd
                });
                SSR_GetGeneralLogDataAdd?.Invoke(KQEmpID, new DateTime(Year, Month, Day, Hour, Minute, Second).ToString());
            }
            return glogs;
        }

        /// <summary>
        /// 读取内存中所有考勤记录
        /// (内部使用中控SSR_GetGeneralLogDataEx函数)
        /// (适应于BW机子,TFT机子读取数据有问题)
        /// </summary>
        /// <param name="ID">考勤机号</param>
        /// <param name="Index">返回当前记录指针</param>
        /// <returns></returns>
        public static List<ModelGLog> SSR_GetGeneralLogDataEx(int ID)
        {
            List<ModelGLog> glogs = new List<ModelGLog>();
            while (ZKGConf.GetZKClass(ID).SSR_GetGeneralLogDataEx
                (ID, out string TEnID, out int TVMode, out int TIOMode, out int TYear, out int TMonth,
                out int TDay, out int THour, out int TMinute, out int TSecond, out string TWork))
            {

                glogs.Add(new ModelGLog()
                {
                    MachineNumber = ID,
                    EnrollNumber = TEnID,
                    VerifyMode = TVMode,
                    InOutMode = TIOMode,
                    dateTime = new DateTime(TYear, TMonth, TDay, THour, TMinute, TSecond),
                    WorkCode = Convert.ToInt32(TWork)
                });
            }
            return glogs;
        }

        /// <summary>
        /// 读取内存中所有考勤记录
        /// (内部使用中控GetGeneralLogDataStr函数)
        /// (适应于BW机子,TFT机子读取数据有问题)
        /// </summary>
        /// <param name="ID">考勤机号</param>
        /// <param name="Index">返回当前记录指针</param>
        /// <returns></returns>s
        public static List<ModelGLog> GetGeneralLogDataStr(int ID)
        {
            //变量
            string IPAdd;
            List<ModelGLog> glogs = new List<ModelGLog>();
            int TEnID = 0, TVMode = 0, TIOMode = 0;
            string dts = "";
            //获取考勤机IP地址
            IPAdd = ZKAPIOriginal.GetDeviceIP(ID);
            //读取考勤记录到List
            while (ZKGConf.GetZKClass(ID).GetGeneralLogDataStr
                (ID, ref TEnID, ref TVMode, ref TIOMode, ref dts))
            {
                DateTime.TryParse(dts, out DateTime tmpdt);
                glogs.Add(new ModelGLog()
                {
                    MachineNumber = ID,
                    EnrollNumber = TEnID.ToString(),
                    VerifyMode = TVMode,
                    InOutMode = TIOMode,
                    dateTime = tmpdt,
                    WorkCode = 0
                });
            }
            return glogs;
        }

        #endregion

        #region 考勤员工处理
        /// <summary>
        /// 设置指定考勤机指定ID的姓名,密码,权限,启用标志(如果没有此ID的用户则会创建)
        /// </summary>
        /// <param name="ID"></param>
        /// <param name="EnrollID"></param>
        /// <param name="Name"></param>
        /// <param name="Password"></param>
        /// <param name="Privilege"></param>
        /// <param name="Enable"></param>
        /// <returns></returns>
        public static bool SetPersonnelPassAuth(int ID, string EnrollID, string Name, string Password, int Privilege, bool Enable)
        {
            return ZKAPIOriginal.SSR_SetUserInfo(ID, EnrollID, Name, Password, Privilege, Enable);
        }

        #endregion

        #region #region 5.2数据管理相关函数

        /// <summary>
        /// 5.2.1.10清除机器内所有考勤记录
        /// </summary>
        /// <param name="ID">考勤机ID</param>
        /// <returns></returns>
        public static bool ClearGLog(int ID)
        {
            return ZKAPIOriginal.ClearGLog(ID);
        }

        /// <summary>
        /// 5.2.3.16设置用户信息, 若机器内没用该用户，则会创建该用户
        /// </summary>
        /// <param name="ID">考勤机ID</param>
        /// <param name="EnrollID">考勤号</param>
        /// <param name="Name">名字</param>
        /// <param name="Password">密码</param>
        /// <param name="Privilege">权限</param>
        /// <param name="Enable">启用</param>
        /// <returns></returns>
        public static bool SSR_SetUserInfo(int ID, string EnrollID, string Name, string Password, int Privilege, bool Enable)
        {
            return ZKAPIOriginal.SSR_SetUserInfo(ID, EnrollID, Name, Password, Privilege, Enable);
        }
        /// <summary>
        /// 5.2.4.5删除登记数据
        /// </summary>
        /// <param name="ID">考勤机ID</param>
        /// <param name="EnrollID">考勤号</param>
        /// <param name="BackupID">指纹索引</param>
        /// <returns></returns>
        public static bool SSR_DeleteEnrollDataExt(int ID, string EnrollID, int BackupID)
        {
            return ZKAPIOriginal.SSR_DeleteEnrollDataExt(ID, EnrollID, BackupID);
        }

        /// <summary>
        /// 5.2.5.5以字符串方式上传用户指纹模板
        /// </summary>
        /// <param name="ID">考勤机ID</param>
        /// <param name="EnrollID">考勤号</param>
        /// <param name="FingerIndex">指纹编号</param>
        /// <param name="TmpData">数据</param>
        /// <returns></returns>
        public static bool SSR_SetUserTmpStr(int ID, string EnrollID, int FingerIndex, string TmpData)
        {
            return ZKAPIOriginal.SSR_SetUserTmpStr(ID, EnrollID, FingerIndex, TmpData);
        }

        /// <summary>
        /// 5.2.13.2清除机器内由DataFlag指定的记录
        /// </summary>
        /// <param name="ID">考勤机ID</param>
        /// <param name="DataFlag">需清除的记录类型</param>
        /// <returns></returns>
        public static bool ClearData(int ID,int DataFlag)
        {
            return ZKAPIOriginal.ClearData(ID, DataFlag);
        }

        
        #endregion
    }
}
